package com.whfc.safety.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.base.param.AppFileExportParam;
import com.whfc.base.service.AppExportService;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.enums.AppWarnModuleType;
import com.whfc.common.enums.AppWarnMsgChannel;
import com.whfc.common.exception.BizException;
import com.whfc.common.file.FileHandler;
import com.whfc.common.file.FilePathConfig;
import com.whfc.common.file.FileSizeType;
import com.whfc.common.file.properties.FileExpirationRules;
import com.whfc.common.result.PageData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.*;
import com.whfc.entity.dto.msg.AppMsgToUserDTO;
import com.whfc.entity.dto.msg.PushMsgDTO;
import com.whfc.fuum.dto.SysUserDTO;
import com.whfc.fuum.service.SysUserService;
import com.whfc.safety.dao.*;
import com.whfc.safety.dto.*;
import com.whfc.safety.entity.*;
import com.whfc.safety.enums.*;
import com.whfc.safety.param.*;
import com.whfc.safety.redis.DangerDictRedisDao;
import com.whfc.safety.service.SafetyDangerService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @Description 危大工程
 * @Author hw
 * @Date 2021-08-16 14:29
 * @Version 1.0
 */
@DubboService(interfaceClass = SafetyDangerService.class, version = "1.0.0")
public class SafetyDangerServiceImpl implements SafetyDangerService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SafetyDangerDictMapper safetyDangerDictMapper;

    @Autowired
    private SafetyDangerDictControlMapper safetyDangerDictControlMapper;

    @Autowired
    private SafetyDangerMapper safetyDangerMapper;

    @Autowired
    private SafetyDangerAreaMapper safetyDangerAreaMapper;

    @Autowired
    private SafetyCheckMapper safetyCheckMapper;

    @Autowired
    private SafetyDangerControlMapper safetyDangerControlMapper;

    @Autowired
    private SafetyDangerAttachMapper safetyDangerAttachMapper;

    @Autowired
    private SafetyDangerExtMapper safetyDangerExtMapper;

    @Autowired
    private SafetyCheckImgMapper safetyCheckImgMapper;

    @Autowired
    private SafetyAreaMapper safetyAreaMapper;

    @Autowired
    private SafetyCheckLogMapper safetyCheckLogMapper;

    @Autowired
    private SafetyCheckUserMapper safetyCheckUserMapper;

    @Autowired
    private SafetyCheckExtMapper safetyCheckExtMapper;

    @DubboReference(interfaceClass = SysUserService.class, version = "1.0.0")
    private SysUserService sysUserService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private DangerDictRedisDao dangerDictRedisDao;

    @Autowired
    private FilePathConfig msFilePathConfig;

    @Autowired
    private FileHandler fileHandler;

    @Autowired
    private SafetyIssueTypeMapper safetyIssueTypeMapper;

    private final static String QUALITY_FILE_DESC = "危大工程台账导出";

    private final static String EXCEL_TEMPLATE_PATH = "excelTemp/dangerTemp.xls";

    @DubboReference(interfaceClass = AppExportService.class, version = "1.0.0")
    private AppExportService appExportService;

    @Override
    public List<SafetyDangerDictDTO> dictList() throws BizException {
        logger.info("查询危大字典列表");
        List<SafetyDangerDictDTO> list = dangerDictRedisDao.getDangerDict();
        if (list == null) {
            list = getDangerDict();
            dangerDictRedisDao.addDangerDict(list);
        }
        return list;
    }

    @Override
    public List<SafetyDangerDictControlDTO> dictControlList(Integer dictId) throws BizException {
        logger.info("查询危大字典-管控要点列表");
        List<SafetyDangerDictControlDTO> list = dangerDictRedisDao.getDangerDictControl(dictId);
        if (list == null) {
            list = safetyDangerDictControlMapper.selectByDictId(dictId);
            dangerDictRedisDao.addDangerDictControl(list, dictId);
        }
        return list;
    }

    @Override
    public DangerStatisticalDTO dangerStatistical(Integer deptId) throws BizException {
        logger.info("危大工程台账统计,deptId:{}", deptId);
        Date time = new Date();
        Date startTime = DateUtil.getMonthBegin(time);
        Date endTime = DateUtil.getMonthEnd(time);

        Integer proceedDangerNum = safetyDangerMapper.selectProceedDangerNumByDeptId(deptId, DateUtil.getDateBegin(time), DateUtil.getDateEnd(time));
        Integer areaNum = safetyDangerAreaMapper.selectAreaNumByDeptId(deptId);
        Integer curCheckNum = safetyDangerExtMapper.selectCurCheckNumByDeptId(deptId, startTime, endTime);
        Integer curDangerCheckNum = safetyCheckMapper.selectCurDangerCheckNumByDeptId(deptId, startTime, endTime);
        // TODO: 2021-08-19 本月排查覆盖率需求不清晰默认为百分之0
        String curCheckCoverNum = "0%";
        time = DateUtil.addMonth(time, 1);
        startTime = DateUtil.getMonthBegin(time);
        endTime = DateUtil.getMonthEnd(time);
        Integer proxDangerNum = safetyDangerMapper.selectProxDangerNumByDeptId(deptId, startTime, endTime);
        DangerStatisticalDTO statistical = new DangerStatisticalDTO();
        statistical.setAreaNum(areaNum == null ? 0 : areaNum);
        statistical.setProceedDangerNum(proceedDangerNum == null ? 0 : proceedDangerNum);
        statistical.setCurCheckNum(curCheckNum == null ? 0 : curCheckNum);
        statistical.setCurDangerCheckNum(curDangerCheckNum == null ? 0 : curDangerCheckNum);
        statistical.setCurCheckCoverNum(curCheckCoverNum);
        statistical.setProxDangerNum(proxDangerNum == null ? 0 : proxDangerNum);
        return statistical;
    }

    @Override
    public PageData<SafetyDangerDTO> dangerList(Integer deptId, Integer state, Integer pageNum, Integer pageSize) throws BizException {
        logger.info("危大工程台账列表,deptId：{},pageNum：{},pageSize：{}", deptId, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<SafetyDangerDTO> list = safetyDangerMapper.selectByDeptId(deptId, state);
        PageHelper.clearPage();
        if (!list.isEmpty()) {
            List<Integer> dangerIds = list.stream().map(SafetyDangerDTO::getDangerId).collect(Collectors.toList());
            List<SafetyAreaDTO> safetyAreaDTOS = safetyDangerAreaMapper.selectByDangerIds(dangerIds);
            List<SafetyCheckObjNumDTO> checkNums = safetyCheckMapper.selectDangerCheckNumByDangerIds(dangerIds);
            List<SafetyDangerControlNumDTO> controlNums = safetyDangerControlMapper.selectNumByDangerIds(dangerIds);
            List<SysUserDTO> sysUserDTOS = sysUserService.getUsersByDeptId(deptId);
            for (SafetyDangerDTO dangerDTO : list) {
                List<SafetyAreaDTO> areas = safetyAreaDTOS.stream()
                        .filter(safetyAreaDTO -> safetyAreaDTO.getDangerId().equals(dangerDTO.getDangerId())).collect(Collectors.toList());
                dangerDTO.setAreas(areas);
                SafetyCheckObjNumDTO checkObjNum = checkNums.stream()
                        .filter(safetyCheckObjNumDTO -> safetyCheckObjNumDTO.getDangerId().equals(dangerDTO.getDangerId())).findAny().orElse(null);
                if (checkObjNum != null) {
                    dangerDTO.setCheckNum(checkObjNum.getNum());
                } else {
                    dangerDTO.setCheckNum(0);
                }
                SafetyDangerControlNumDTO controlNum = controlNums.stream()
                        .filter(safetyDangerControlNumDTO -> safetyDangerControlNumDTO.getDangerId().equals(dangerDTO.getDangerId())).findAny().orElse(null);
                if (controlNum != null) {
                    Integer completeNum = controlNum.getCompleteNum();
                    Integer failNum = controlNum.getFailNum();
                    String controlStatistics = completeNum + "/" + (completeNum + failNum);
                    dangerDTO.setControlStatistics(controlStatistics);
                }
                SysUserDTO user = sysUserDTOS.stream().filter(sysUserDTO -> sysUserDTO.getId().equals(dangerDTO.getUserId())).findAny().orElse(null);
                if (user != null) {
                    dangerDTO.setUserPhone(user.getPhone());
                }
                SysUserDTO corpUser = sysUserDTOS.stream().filter(sysUserDTO -> sysUserDTO.getId().equals(dangerDTO.getCorpUserId())).findAny().orElse(null);
                if (corpUser != null) {
                    dangerDTO.setCorpUserPhone(corpUser.getPhone());
                }
            }
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public void exportDanger(Integer deptId, Integer state) throws BizException {
        logger.info("危大工程台账导出,deptId:{},state:{}", deptId, state);

        String fileDesc = QUALITY_FILE_DESC;
        String fileName = RandomUtil.getRandomFileName();
        String suffix = "xls";
        AppFileExportParam fileExport = new AppFileExportParam();
        fileExport.setDeptId(deptId);
        fileExport.setFileName(fileName);
        fileExport.setFileFormat(suffix.toUpperCase());
        fileExport.setFileState(0);
        fileExport.setFileDesc(fileDesc);
        Integer id = appExportService.install(fileExport);
        fileExport.setId(id);
        AppFileExportParam upFileExport = fileExport;
        CompletableFuture.supplyAsync(() -> {
            List<SafetyDangerDTO> list = safetyDangerMapper.selectByDeptId(deptId, state);
            try {
                ClassPathResource resource = new ClassPathResource(EXCEL_TEMPLATE_PATH);
                InputStream templateFileInputStream = resource.getInputStream();
                File tempFile = FileUtil.copyTemplateFile(templateFileInputStream);

                FileInputStream fileInputStream = new FileInputStream(tempFile);
                HSSFWorkbook workbook = new HSSFWorkbook(fileInputStream);
                HSSFSheet sheet = workbook.getSheetAt(0);
                sheet.setDefaultRowHeight((short) 25);
                if (!list.isEmpty()) {
                    List<Integer> dangerIds = list.stream().map(SafetyDangerDTO::getDangerId).collect(Collectors.toList());
                    List<SafetyAreaDTO> safetyAreaDTOS = safetyDangerAreaMapper.selectByDangerIds(dangerIds);


                    HSSFCellStyle style = workbook.createCellStyle();
                    style.setBorderBottom(BorderStyle.THIN);
                    style.setBottomBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
                    style.setBorderLeft(BorderStyle.THIN);
                    style.setLeftBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
                    style.setBorderRight(BorderStyle.THIN);
                    style.setRightBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
                    style.setBorderTop(BorderStyle.THIN);
                    style.setTopBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
                    style.setWrapText(true);
                    style.setAlignment(HorizontalAlignment.CENTER);//水平居中
                    style.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中

                    int rowIdx = 2;
                    for (SafetyDangerDTO danger : list) {
                        HSSFRow row = sheet.createRow(rowIdx);
                        row.createCell(0).setCellValue(rowIdx - 1);
                        row.getCell(0).setCellStyle(style);

                        row.createCell(1).setCellValue(StringUtils.isNotEmpty(danger.getName()) ? danger.getName() : "-");
                        row.getCell(1).setCellStyle(style);

                        List<SafetyAreaDTO> areas = safetyAreaDTOS.stream()
                                .filter(safetyAreaDTO -> safetyAreaDTO.getDangerId().equals(danger.getDangerId())).collect(Collectors.toList());
                        String areasNames = areas.stream().reduce(new StringBuffer(), (sb, s) -> sb.append(s.getName()).append(','), StringBuffer::append).toString();
                        row.createCell(2).setCellValue(StringUtils.isNotEmpty(areasNames) ? areasNames : "-");
                        row.getCell(2).setCellStyle(style);

                        row.createCell(3).setCellValue(danger.getPlanStartTime() != null ? DateUtil.formatDate(danger.getPlanStartTime()) : "-");
                        row.getCell(3).setCellStyle(style);

                        row.createCell(4).setCellValue(danger.getPlanEndTime() != null ? DateUtil.formatDate(danger.getPlanEndTime()) : "-");
                        row.getCell(4).setCellStyle(style);

                        row.createCell(5).setCellValue(StringUtils.isNotEmpty(danger.getSurvey()) ? danger.getSurvey() : "-");
                        row.getCell(5).setCellStyle(style);

                        row.createCell(6).setCellValue(danger.getUserName());
                        row.getCell(6).setCellStyle(style);
                        rowIdx++;
                    }
                }

                // 保存excel
                FileOutputStream fos = new FileOutputStream(tempFile);
                workbook.write(fos);
                fos.flush();
                fos.close();

                //上传oss
                FileInputStream inputStream = new FileInputStream(tempFile);
                String path = msFilePathConfig.getFilePath("safety/export", fileName, suffix);
                String upload = fileHandler.upload(path, inputStream, FileExpirationRules.DAYS_7);
                upFileExport.setFileUrl(upload);
                upFileExport.setFileState(1);
                appExportService.update(upFileExport);
            } catch (Exception e) {
                logger.error("危大工程台账导出异常", e);
                e.printStackTrace();
            }
            return null;
        });


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addDanger(SafetyDangerAddParam param) throws BizException {
        logger.info("新建危大工程台账,param:{}", param);
        SafetyDanger safetyDanger = new SafetyDanger();
        BeanUtils.copyProperties(param, safetyDanger);
        safetyDangerMapper.insertSelective(safetyDanger);
        List<Integer> areaIds = param.getAreaIds();
        if (areaIds != null && !areaIds.isEmpty()) {
            safetyDangerAreaMapper.insertAll(param.getDeptId(), safetyDanger.getId(), areaIds);
        }
        List<SafetyDangerAttachParam> attachUrls = param.getAttachUrls();
        if (attachUrls != null && !attachUrls.isEmpty()) {
            safetyDangerAttachMapper.insertAll(param.getDeptId(), safetyDanger.getId(), safetyDanger.getId(), attachUrls, param.getUserId(), param.getUserName());
        }
        List<Integer> controlIds = param.getControlIds();
        if (controlIds != null && !controlIds.isEmpty()) {
            safetyDangerControlMapper.insertAll(param.getDeptId(), safetyDanger.getId(), controlIds);
        }
    }

    @Override
    public void editDanger(SafetyDangerEditParam param) throws BizException {
        logger.info("修改危大工程台账,param:{}", param);
        Integer dangerId = param.getDangerId();
        SafetyDanger safetyDanger = safetyDangerMapper.selectByPrimaryKey(dangerId);
        if (safetyDanger == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "编辑数据不存在");
        }
        if (safetyDanger.getState().equals(SafetyDangerState.SUCCESS.getValue())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据已完成无法修改");
        }
        BeanUtils.copyProperties(param, safetyDanger);
        safetyDangerMapper.updateByPrimaryKeySelective(safetyDanger);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delDanger(Integer dangerId) throws BizException {
        logger.info("删除危大工程台账，dangerId：{}", dangerId);
        SafetyDanger safetyDanger = safetyDangerMapper.selectByPrimaryKey(dangerId);
        if (safetyDanger.getState().equals(SafetyDangerState.SUCCESS.getValue())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据已完成无法删除");
        }
        safetyDangerControlMapper.delByDangerId(dangerId);
        safetyDangerAttachMapper.delByDangerId(dangerId, null);
        safetyDangerAreaMapper.delByDangerId(dangerId);
        safetyDangerExtMapper.delByDangerId(dangerId);
        safetyDangerMapper.del(dangerId);
    }

    @Override
    public PageData<SafetyDangerExtDTO> dangerExt(Integer dangerId, Integer type, Integer pageNum, Integer pageSize) throws BizException {
        logger.info("查询当前进度、施工旁站、一般验收、排查记录,dangerId：{},type：{},pageNum：{},pageSize：{}", dangerId, type, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<SafetyDangerExtDTO> list = safetyDangerExtMapper.selectByDangerId(dangerId, type);
        PageHelper.clearPage();
        if (!list.isEmpty()) {
            List<Integer> extIds = list.stream().map(SafetyDangerExtDTO::getExtId).collect(Collectors.toList());
            List<SafetyDangerAcceptDTO> attachList = safetyDangerAttachMapper.selectByObjIdsAndType(dangerId, extIds, Collections.singletonList(type));
            List<SafetyAreaDTO> safetyAreaDTOS = safetyDangerAreaMapper.selectByDangerIds(Arrays.asList(dangerId));

            for (SafetyDangerExtDTO safetyDangerExtDTO : list) {
                List<String> urls = attachList.stream()
                        .filter(safetyDangerAcceptDTO -> safetyDangerAcceptDTO.getObjId().equals(safetyDangerExtDTO.getExtId()))
                        .map(SafetyDangerAcceptDTO::getUrl).collect(Collectors.toList());
                if (!urls.isEmpty()) {
                    safetyDangerExtDTO.setUrls(urls);
                }
                SafetyAreaDTO area = safetyAreaDTOS.stream()
                        .filter(safetyAreaDTO -> safetyAreaDTO.getAreaId().equals(safetyDangerExtDTO.getAreaId())).findAny().orElse(null);
                if (area != null) {
                    safetyDangerExtDTO.setAreaId(area.getAreaId());
                    safetyDangerExtDTO.setAreaName(area.getName());
                }
            }
        }
        return PageUtil.pageData(PageInfo.of(list));
    }


    @Override
    public void dangerAddExt(SafetyDangerAddExtParam param) throws BizException {
        logger.info("添加当前进度、施工旁站、一般验收、排查记录，param：{}", param);
        Integer dangerId = param.getDangerId();
        SafetyDanger safetyDanger = safetyDangerMapper.selectByPrimaryKey(dangerId);
        if (safetyDanger.getState().equals(SafetyDangerState.SUCCESS.getValue())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据已完成无法添加数据");
        }
        SafetyDangerExt ext = new SafetyDangerExt();
        BeanUtils.copyProperties(param, ext);
        ext.setDeptId(safetyDanger.getDeptId());
        safetyDangerExtMapper.insertSelective(ext);
        List<String> urls = param.getUrls();
        if (urls != null && !urls.isEmpty()) {
            List<SafetyDangerAttachParam> attachUrls = new ArrayList<>();
            urls.forEach(s -> {
                SafetyDangerAttachParam attachParam = new SafetyDangerAttachParam();
                attachParam.setUrl(s);
                attachParam.setType(param.getType());
                attachUrls.add(attachParam);
            });
            safetyDangerAttachMapper.insertAll(safetyDanger.getDeptId(), safetyDanger.getId(), ext.getId(), attachUrls, param.getUserId(), param.getUserName());
        }
    }

    @Override
    public void dangerEditExt(SafetyDangerEditExtParam param) throws BizException {
        logger.info("修改当前进度、施工旁站、一般验收、排查记录，param：{}", param);
        Integer dangerId = param.getDangerId();
        SafetyDanger safetyDanger = safetyDangerMapper.selectByPrimaryKey(dangerId);
        if (safetyDanger.getState().equals(SafetyDangerState.SUCCESS.getValue())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据已完成无法修改数据");
        }
        Integer extId = param.getExtId();
        SafetyDangerExt ext = safetyDangerExtMapper.selectByPrimaryKey(extId);
        BeanUtils.copyProperties(param, ext);
        ext.setType(null);
        safetyDangerExtMapper.updateByPrimaryKeySelective(ext);
        List<String> urls = param.getUrls();
        Integer type = param.getType();
        safetyDangerAttachMapper.delByDangerIdAndObjIdAndType(dangerId, extId, type);
        if (urls != null && !urls.isEmpty()) {
            List<SafetyDangerAttachParam> attachUrls = new ArrayList<>();
            urls.forEach(s -> {
                SafetyDangerAttachParam attachParam = new SafetyDangerAttachParam();
                attachParam.setUrl(s);
                attachParam.setType(param.getType());
                attachUrls.add(attachParam);
            });
            safetyDangerAttachMapper.insertAll(safetyDanger.getDeptId(), safetyDanger.getId(), extId, attachUrls, param.getUserId(), param.getUserName());
        }
    }

    @Override
    public void dangerExtDel(Integer dangerId, Integer extId, Integer type) throws BizException {
        logger.info("删除当前进度、施工旁站、一般验收、排查记录，dangerId:{},extId：{},type：{}", dangerId, extId, type);
        SafetyDanger safetyDanger = safetyDangerMapper.selectByPrimaryKey(dangerId);
        if (safetyDanger.getState().equals(SafetyDangerState.SUCCESS.getValue())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据已完成无法删除");
        }
        safetyDangerExtMapper.delByIdAndType(extId, type);
        safetyDangerAttachMapper.delByDangerIdAndObjIdAndType(dangerId, extId, type);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<SafetyDangerAcceptDTO> dangerAttachList(Integer dangerId) throws BizException {
        logger.info("危大文件列表,dangerId:{}", dangerId);
        return safetyDangerAttachMapper.selectByObjIdsAndType(dangerId, Collections.singletonList(dangerId), Arrays.asList(1, 2, 3, 4));
    }

    @Override
    public void dangerAttachDel(Integer attachId) throws BizException {
        logger.info("删除危大文件,attachId：{}", attachId);
        safetyDangerAttachMapper.delById(attachId);
    }

    @Override
    public void dangerAttachSave(SafetyDangerAttachSaveParam param) throws BizException {
        logger.info("保存危大文件,param:{}", param);
        Integer dangerId = param.getDangerId();
        SafetyDanger safetyDanger = safetyDangerMapper.selectByPrimaryKey(dangerId);
        if (safetyDanger == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据不存在");
        }
        if (safetyDanger.getState().equals(SafetyDangerState.SUCCESS.getValue())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据已完成无法删除");
        }
        safetyDangerAttachMapper.delByDangerId(dangerId, Arrays.asList(1, 2, 3, 4));
        List<SafetyDangerAttachParam> attachUrls = param.getAttachUrls();
        if (attachUrls != null && !attachUrls.isEmpty()) {
            attachUrls.forEach(safetyDangerAttachParam -> {
                if (safetyDangerAttachParam.getSize() != null) {
                    String sizeStr = FileSizeType.getFileSize(safetyDangerAttachParam.getSize());
                    safetyDangerAttachParam.setSizeStr(sizeStr);
                }
            });
            safetyDangerAttachMapper.insertAll(safetyDanger.getDeptId(), dangerId, dangerId, attachUrls, param.getUserId(), param.getUserName());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dangerCheckAdd(SafetyDangerCheckAddParam param) throws BizException {
        logger.info("新增问题隐患,param:{}", param);
        Integer checkId = addCheck(param);
        SafetyCheckExt ext = new SafetyCheckExt();
        BeanUtils.copyProperties(param, ext);
        ext.setCheckId(checkId);
        ext.setObjId(param.getDangerId());
        safetyCheckExtMapper.insertSelective(ext);
    }

    @Override
    public SafetyDangerCheckNumDTO dangerCheckNum(Integer dangerId) throws BizException {
        logger.info("问题隐患统计,dangerId：{}", dangerId);
        Integer checkNum = safetyCheckMapper.selectDangerCheckNumByDangerId(dangerId);
        Integer patrolNum = safetyDangerExtMapper.selectCheckNumByDangerId(dangerId);
        SafetyDangerCheckNumDTO num = new SafetyDangerCheckNumDTO();
        num.setCheckNum(checkNum);
        num.setPatrolNum(patrolNum);
        return num;
    }

    @Override
    public PageData<SafetyCheckDTO> dangerCheckList(Integer dangerId, Integer pageNum, Integer pageSize) throws BizException {
        logger.info("问题隐患列表,dangerId：{},pageNum：{},pageSize：{}", dangerId, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<SafetyCheckDTO> list = safetyCheckMapper.selectByObjId(dangerId);
        PageHelper.clearPage();
        if (!list.isEmpty()) {
            for (SafetyCheckDTO safetyCheckDTO : list) {
                List<String> urls = safetyCheckImgMapper.selectByCheckId(safetyCheckDTO.getCheckId(), SafetyCheckUserType.REPORTER.getValue(), null);
                safetyCheckDTO.setImgUrlList(urls);
            }
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public SafetyCheckDescDTO dangerCheckDesc(Integer checkId) throws BizException {
        logger.info("问题隐患详情,checkId:{}", checkId);
        SafetyCheckDescDTO checkDescDTO = safetyCheckMapper.selectObjById(checkId);
        if (Objects.isNull(checkDescDTO)) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "查询数据不存在");
        }
        List<String> urls = safetyCheckImgMapper.selectByCheckId(checkId, SafetyOptionType.REPORT.getValue(), checkDescDTO.getLogId());
        SafetyIssueType safetyIssueType = safetyIssueTypeMapper.selectByIssueTypeId(checkDescDTO.getIssueTypeId());
        if(null == safetyIssueType){
            checkDescDTO.setIssueTypeName("其他");
        }else{
            checkDescDTO.setIssueTypeName(safetyIssueType.getName());
        }
        checkDescDTO.setImgUrlList(urls);
        SafetyArea area = safetyAreaMapper.selectByPrimaryKey(checkDescDTO.getObjId());
        if (area != null) {
            checkDescDTO.setAreaName(area.getName());
        }
        List<SafetyCheckLogListDTO> logList = safetyCheckLogMapper.selectByCheckId(checkId);
        for (SafetyCheckLogListDTO logListDTO : logList) {
            List<String> logUrls = safetyCheckImgMapper.selectByCheckId(checkId, logListDTO.getOpType(), logListDTO.getLogId());
            logListDTO.setImgUrlList(logUrls);
        }
        checkDescDTO.setLogList(logList);
        checkDescDTO.setUserList(safetyCheckUserMapper.selectByCheckId(checkId));
        return checkDescDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dangerCheckDel(Integer dangerId, Integer checkId) throws BizException {
        logger.info("删除问题隐患,dangerId：{},checkId：{}", dangerId, checkId);
        SafetyCheck safetyCheck = safetyCheckMapper.selectByPrimaryKey(checkId);
        if (safetyCheck == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "删除数据不存在");
        }
        if (SafetyCheckState.SUCCESS.getValue().equals(safetyCheck.getState())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "已完成数据不可删除");
        }
        safetyCheckImgMapper.del(checkId);
        safetyCheckLogMapper.del(checkId);
        safetyCheckUserMapper.del(checkId);
        safetyCheckMapper.del(checkId);
    }

    @Override
    public PageData<SafetyDangerAcceptDTO> dangerAcceptList(Integer dangerId, Integer pageNum, Integer pageSize) throws BizException {
        logger.info("验收表验收列表,dangerId:{},pageNum:{},pageSize:{}", dangerId, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<SafetyDangerAcceptDTO> list = safetyDangerAttachMapper.selectByObjIdsAndType(dangerId, Collections.singletonList(dangerId), Collections.singletonList(8));
        PageHelper.clearPage();
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public void dangerAcceptSave(SafetyDangerAttachSaveParam param) throws BizException {
        logger.info("保存验收表验收,param:{}", param);
        Integer dangerId = param.getDangerId();
        SafetyDanger safetyDanger = safetyDangerMapper.selectByPrimaryKey(dangerId);
        if (safetyDanger == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据不存在");
        }
        if (safetyDanger.getState().equals(SafetyDangerState.SUCCESS.getValue())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据已完成无法删除");
        }
        safetyDangerAttachMapper.delByDangerId(dangerId, Arrays.asList(8));
        List<SafetyDangerAttachParam> attachUrls = param.getAttachUrls();
        if (attachUrls != null && !attachUrls.isEmpty()) {
            attachUrls.forEach(safetyDangerAttachParam -> {
                if (safetyDangerAttachParam.getSize() != null) {
                    String sizeStr = FileSizeType.getFileSize(safetyDangerAttachParam.getSize());
                    safetyDangerAttachParam.setSizeStr(sizeStr);
                }
            });
            safetyDangerAttachMapper.insertAll(safetyDanger.getDeptId(), dangerId, dangerId, attachUrls, param.getUserId(), param.getUserName());
        }
    }

    @Override
    public void dangerComplete(Integer dangerId) throws BizException {
        logger.info("完成危大数据,dangerId:{}", dangerId);
        SafetyDanger safetyDanger = safetyDangerMapper.selectByPrimaryKey(dangerId);
        if (safetyDanger.getState().equals(SafetyDangerState.SUCCESS.getValue())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据已完成");
        }
        List<SafetyCheckObjNumDTO> nums = safetyCheckMapper.selectDangerCheckNumByDangerIds(Collections.singletonList(dangerId));
        if (!nums.isEmpty()) {
            SafetyCheckObjNumDTO num = nums.get(0);
            if (num.getNum() > 0) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据存在未完成的问题隐患，无法完成");
            }
        }
        List<SafetyDangerControlNumDTO> controlNums = safetyDangerControlMapper.selectNumByDangerIds(Collections.singletonList(dangerId));
        if (!controlNums.isEmpty()) {
            SafetyDangerControlNumDTO controlNumDTO = controlNums.get(0);
            Integer failNum = controlNumDTO.getFailNum();
            if (failNum > 0) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据存在未完成的管控要点，无法完成");
            }
        }
        safetyDanger.setState(SafetyDangerState.SUCCESS.getValue());
        safetyDangerMapper.updateByPrimaryKeySelective(safetyDanger);
    }

    @Override
    public List<SafetyDangerControlDTO> dangerControlList(Integer dangerId) throws BizException {
        logger.info("查询管控要点：dangerId：{}", dangerId);
        return safetyDangerControlMapper.selectByDangerId(dangerId);
    }

    @Override
    public void dangerControlComplete(SafetyDangerControlCompleteParam param) throws BizException {
        logger.info("提交管控要点,param:{}", param);
        Integer controlId = param.getControlId();
        Integer state = param.getState();
        SafetyDangerControl control = safetyDangerControlMapper.selectByPrimaryKey(controlId);
        if (control == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前数据不存在");
        }
        control.setState(state);
        safetyDangerControlMapper.updateByPrimaryKeySelective(control);
    }


    @Override
    public List<Integer> getDangerIds() throws BizException {
        return safetyDangerMapper.selectDangerIdAll();
    }

    @Override
    public void updateOverdue(List<Integer> dangerIds) throws BizException {
        safetyDangerMapper.updateOverdue(dangerIds);
    }

    private Integer addCheck(SafetyCheckParam safetyCheckParam) throws BizException {
        if (UrgencyLevel.parseValue(safetyCheckParam.getUrgency()) == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "紧急程度编码不存在");
        }
        if (safetyCheckParam.getCheckUsers().stream().distinct().count() < safetyCheckParam.getCheckUsers().size()) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "安全问题上报用户信息重复");
        }
        //判断检查部位ID是否有值，没有值得情况为手动录入
        if (safetyCheckParam.getPartId() == null) {
            safetyCheckParam.setPartId(-1);
        }
        //判断问题类型ID是否有值，没有值得情况为手动录入
        if (safetyCheckParam.getIssueTypeId() == null) {
            safetyCheckParam.setIssueTypeId(-1L);
            //特殊处理当问题内别没有时数据库会返回异常需要手动存入值（手动录入）
            safetyCheckParam.setIssueTypeName("手动录入");
        }
        //判断问题明细是否有值，没有值得情况为手动录入
        if (safetyCheckParam.getIssueId() == null) {
            safetyCheckParam.setIssueId(-1L);
        }

        SafetyCheck safetyCheck = new SafetyCheck();
        //开始保存安全问题主表
        insertCheck(safetyCheckParam, safetyCheck);
        //开始保存安全问题记录相关人员和安全问题流程处理
        SafetyCheckLog checkLog = inserCheckUserAndLog(safetyCheckParam, safetyCheck);

        for (String imgUrl : safetyCheckParam.getImgUrls()) {
            SafetyCheckImg checkImg = new SafetyCheckImg();
            checkImg.setCheckId(safetyCheck.getId());
            checkImg.setLogId(checkLog.getId());
            checkImg.setImgUrl(imgUrl);
            safetyCheckImgMapper.insertSelective(checkImg);
        }
        SafetyCheckDTO safetyCheckDTO = new SafetyCheckDTO();
        BeanUtils.copyProperties(safetyCheck, safetyCheckDTO);
        safetyCheckDTO.setCheckId(safetyCheck.getId());
        generateMessage(safetyCheckDTO, safetyCheckParam.getCheckUsers());
        return safetyCheck.getId();
    }

    /**
     * @Author hw
     * @Description 保存问题上报主表
     * @Date 2020/8/5
     * @param: safetyCheckParam
     * @param: safetyCheck
     * @return: null
     **/
    private void insertCheck(SafetyCheckParam safetyCheckParam, SafetyCheck safetyCheck) {

        //计算整改需要的时间
        Date rectifyStartTime = new Date();
        LocalDate now = LocalDateTime.ofInstant(rectifyStartTime.toInstant(), ZoneId.systemDefault()).toLocalDate();
        LocalDate endTime = LocalDateTime.ofInstant(safetyCheckParam.getRectifyDuration().toInstant(), ZoneId.systemDefault()).toLocalDate();
        Long duration = endTime.toEpochDay() - now.toEpochDay();

        BeanUtils.copyProperties(safetyCheckParam, safetyCheck);


        safetyCheck.setRectifyDuration(duration.intValue());
        safetyCheck.setRectifyStartTime(rectifyStartTime);
        safetyCheck.setRectifyEndTime(safetyCheckParam.getRectifyDuration());
        safetyCheck.setCheckTime(rectifyStartTime);
        //新增问题上报是默认待整改
        safetyCheck.setState(SafetyCheckState.TO_BE_RECTIFIED.getValue());
        //新增问题上报默认为未超期
        safetyCheck.setOverdue(OverdueStatus.NOT_OVERDUE.getValue());

        safetyCheckMapper.insertSelective(safetyCheck);

    }

    /**
     * @param :safetyCheckParam
     * @param :safetyCheck
     * @Author hw
     * @Description 保存安全问题记录相关人员和安全问题流程处理
     * @Date 2020/8/5
     * @return: SafetyCheckLog
     **/
    private SafetyCheckLog inserCheckUserAndLog(SafetyCheckParam safetyCheckParam, SafetyCheck safetyCheck) {
        SafetyCheckLog checkLog = null;
        for (SafetyCheckUserParam userParam : safetyCheckParam.getCheckUsers()) {
            if (SafetyCheckUserType.parseValue(userParam.getType()) == null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "人员类型编码不存在");
            }
            //判断对应人员是否为上报人如果是上报人需要在安全问题流程表添加数据
            if (SafetyCheckUserType.REPORTER.getValue().equals(userParam.getType())) {
                checkLog = new SafetyCheckLog();
                checkLog.setCheckId(safetyCheck.getId());
                checkLog.setOpType(SafetyCheckUserType.REPORTER.getValue());
                checkLog.setOpUserId(userParam.getUserId());
                checkLog.setOpUserName(userParam.getUserName());
                checkLog.setOpTime(new Date());
                safetyCheckLogMapper.insertSelective(checkLog);
            }
            //储存安全问题相关人员信息
            SafetyCheckUser checkUser = new SafetyCheckUser();
            checkUser.setCheckId(safetyCheck.getId());
            checkUser.setType(userParam.getType());
            checkUser.setUserId(userParam.getUserId());
            checkUser.setUserName(userParam.getUserName());
            checkUser.setUserPhone(userParam.getUserPhone());
            safetyCheckUserMapper.insertSelective(checkUser);
        }
        return checkLog;
    }


    /**
     * 发送报警消息
     *
     * @param qualityCheckDTO
     * @param checkUsers
     */
    private void generateMessage(SafetyCheckDTO qualityCheckDTO, List<SafetyCheckUserParam> checkUsers) {
        Integer checkId = qualityCheckDTO.getCheckId();
        Integer deptId = qualityCheckDTO.getDeptId();
        Date checkTime = qualityCheckDTO.getCheckTime();
        String checkUserName = qualityCheckDTO.getCheckUserName();
        //接收消息人员
        //整改人列表
        List<AppMsgToUserDTO> rectifyUserList = new ArrayList<>();
        //抄送人列表
        List<AppMsgToUserDTO> ccUserList = new ArrayList<>();
        for (SafetyCheckUserParam checkUser : checkUsers) {
            AppMsgToUserDTO toUserDTO = new AppMsgToUserDTO();
            toUserDTO.setUserId(checkUser.getUserId());
            toUserDTO.setNickName(checkUser.getUserName());
            toUserDTO.setPhone(checkUser.getUserPhone());
            if (SafetyCheckUserType.REPORTER.getValue().equals(checkUser.getType())) {
                checkUserName = checkUser.getUserName();
            }
            if (SafetyCheckUserType.RECTIFIER.getValue().equals(checkUser.getType())) {
                rectifyUserList.add(toUserDTO);
            }
            if (SafetyCheckUserType.CC.getValue().equals(checkUser.getType())) {
                ccUserList.add(toUserDTO);
            }
        }
        //接收通道
        List<Integer> msgChannelList = new ArrayList<>();
        msgChannelList.add(AppWarnMsgChannel.WXMP.value());
        msgChannelList.add(AppWarnMsgChannel.MS.value());
        //检查时间
        String time = DateUtil.formatDate(checkTime, "yyyy-MM-dd HH:mm");
        //发送消息给整改人
        String rectifyTitle = SafetyMsgTemplate.RECTIFIED.getTitle();
        String rectifyContent = String.format(SafetyMsgTemplate.RECTIFIED.getContent(), checkUserName, time);

        PushMsgDTO pushMsgDTO = new PushMsgDTO();
        pushMsgDTO.setDeptId(deptId);
        pushMsgDTO.setTitle(rectifyTitle);
        pushMsgDTO.setContent(rectifyContent);
        pushMsgDTO.setModuleType(AppWarnModuleType.SAFETY.value());
        pushMsgDTO.setMsgObjectId(String.valueOf(checkId));
        pushMsgDTO.setMsgChannelList(msgChannelList);
        pushMsgDTO.setToUserList(rectifyUserList);
        pushMsgDTO.setTime(checkTime);
        //发送消息给抄送人
        String ccTitle = SafetyMsgTemplate.SUCCESS.getTitle();
        String ccContent = String.format(SafetyMsgTemplate.SUCCESS.getContent(), checkUserName, time);

        PushMsgDTO ccPushMsgDTO = new PushMsgDTO();
        ccPushMsgDTO.setDeptId(deptId);
        ccPushMsgDTO.setTitle(ccTitle);
        ccPushMsgDTO.setContent(ccContent);
        ccPushMsgDTO.setModuleType(AppWarnModuleType.SAFETY.value());
        ccPushMsgDTO.setMsgObjectId(String.valueOf(checkId));
        ccPushMsgDTO.setMsgChannelList(msgChannelList);
        ccPushMsgDTO.setToUserList(ccUserList);
        ccPushMsgDTO.setTime(checkTime);
        try {
            amqpTemplate.convertAndSend(QueueConst.PUSH_MSG_EXCHANGE, "", JSONUtil.toString(pushMsgDTO));
            amqpTemplate.convertAndSend(QueueConst.PUSH_MSG_EXCHANGE, "", JSONUtil.toString(ccPushMsgDTO));
        } catch (Exception ex) {
            logger.error("", ex);
        }

    }

    private List<SafetyDangerDictDTO> getDangerDict() {
        List<SafetyDangerDictDTO> dicts = safetyDangerDictMapper.selectAll();
        if (!dicts.isEmpty()) {
            Map<Integer, SafetyDangerDictDTO> map = new HashMap<>();
            for (SafetyDangerDictDTO dangerDict : dicts) {
                if (map.containsKey(dangerDict.getPid())) {
                    SafetyDangerDictDTO data = map.get(dangerDict.getPid());
                    dangerDict.setDescriptionId(dangerDict.getDictId());
                    dangerDict.setDictId(null);
                    List<SafetyDangerDictDTO> list = data.getDescriptions();
                    if (list == null) {
                        list = new ArrayList<>();
                    }
                    list.add(dangerDict);
                    data.setDescriptions(list);
                    continue;
                }
                map.put(dangerDict.getDictId(), dangerDict);
            }

            return new ArrayList<>(map.values());
        }
        return new ArrayList<>();
    }
}
